/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Parser;

import java.util.ArrayList;
import lowlevel.Attribute;
import lowlevel.Function;
import lowlevel.Operand;
import lowlevel.Operand.OperandType;
import lowlevel.Operation;
import lowlevel.Operation.OperationType;

/**
 *
 * @author maxmuhlenkamp
 */
public class CallExpression extends Expression{
    Identifier id;
    ArrayList<Expression> args;
    
    public CallExpression(Identifier id, ArrayList<Expression> args){
        this.id = id;
        this.args = args;
    }

    @Override
    void print(String indent) {
        CMinusParser.oFile.println(indent + "CallExpression");
        id.print(indent + "  ");
        CMinusParser.oFile.println(indent + "  Args");
        if(args == null){
            CMinusParser.oFile.println(indent + "    null");
        }
        else{
            for(int i = 0; i < args.size(); i++){
                args.get(i).print(indent + "    ");
            }
        }
        CMinusParser.oFile.flush();
    }

    @Override
    public void genLLCode(Function func) {
        for(int i = 0; i < args.size(); i++){
            // gen LL code on expressions
            Expression expr = args.get(i);
            expr.genLLCode(func);
            
            // pass the parameters
            Operation pass = new Operation(OperationType.PASS, func.getCurrBlock());
            pass.addAttribute(new Attribute("PARAM_NUM", ((Integer)i).toString()));
            Operand src0 = new Operand(OperandType.REGISTER, expr.getRegNum());
            pass.setSrcOperand(0, src0);
            func.getCurrBlock().appendOper(pass);
        }
        
        // call the function
        Operation call = new Operation(OperationType.CALL, func.getCurrBlock());
        call.addAttribute(new Attribute("numParams", ((Integer)args.size()).toString()));
        Operand src0 = new Operand(OperandType.STRING, id.idName);
        call.setSrcOperand(0, src0);
        func.getCurrBlock().appendOper(call);
        
        // do the return macro
        regNum = func.getNewRegNum();
        Operation ret = new Operation(OperationType.ASSIGN, func.getCurrBlock());
        Operand sr0 = new Operand(OperandType.MACRO, "RetReg");
        Operand dst0 = new Operand(OperandType.REGISTER, regNum);
        ret.setSrcOperand(0, sr0);
        ret.setDestOperand(0, dst0);
        func.getCurrBlock().appendOper(ret);
    }
}
